﻿using System;
using System.Collections.Generic;
using Aproll.DataDefine;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit.RevitExtension;
using YJKArchMethodLibrary.Utils;

namespace Aproll.BaseLineManage
{
	public class BaseLineController
	{
		public BaseLineController(ExternalCommandData commandData)
		{
			this.m_Revit = commandData;
			this.m_Doc = this.m_Revit.Application.ActiveUIDocument.Document;
			this.m_ActiveView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			this.GetLineStyle();
		}

		public bool SearchBaseLineByWall()
		{
			PathAutoSearcher pathAutoSearcher = new PathAutoSearcher(this.m_Revit);
			List<Curve> list = new List<Curve>();
			if (!pathAutoSearcher.SelectExternalProfile(ref list))
			{
				return false;
			}
			foreach (Curve curve in list)
			{
				EdgeInfo edgeInfo = new EdgeInfo(curve, false);
				BaseLineSegment segment = new BaseLineSegment(edgeInfo);
				string text = "";
				this.AddBaseLineSegment(segment, ref text);
			}
			return true;
		}

		public void MergeLinkedCurve(ref List<EdgeInfo> edgeLoop)
		{
			for (int i = 0; i < edgeLoop.Count; i++)
			{
				for (int j = i + 1; j < edgeLoop.Count; j++)
				{
					if (edgeLoop[i].IsArc == edgeLoop[j].IsArc)
					{
						XYZ xyz;
						XYZ xyz2;
						if (edgeLoop[i].StartPoint.IsAlmostEqualTo(edgeLoop[j].EndPoint))
						{
							xyz = edgeLoop[j].StartPoint;
							xyz2 = edgeLoop[i].EndPoint;
						}
						else if (edgeLoop[i].StartPoint.IsAlmostEqualTo(edgeLoop[j].StartPoint))
						{
							xyz = edgeLoop[i].EndPoint;
							xyz2 = edgeLoop[j].EndPoint;
						}
						else if (edgeLoop[i].EndPoint.IsAlmostEqualTo(edgeLoop[j].StartPoint))
						{
							xyz = edgeLoop[i].StartPoint;
							xyz2 = edgeLoop[j].EndPoint;
						}
						else
						{
							if (!edgeLoop[i].EndPoint.IsAlmostEqualTo(edgeLoop[j].EndPoint))
							{
								goto IL_280;
							}
							xyz = edgeLoop[i].StartPoint;
							xyz2 = edgeLoop[j].StartPoint;
						}
						EdgeInfo edgeInfo;
						if (edgeLoop[i].IsArc)
						{
							if (!Geometry.IsEqual(edgeLoop[i].Normal, edgeLoop[j].Normal))
							{
								goto IL_280;
							}
							bool isAnticlockwise = false;
							if (Geometry.IsEqual(edgeLoop[i].Normal, XYZ.BasisZ))
							{
								isAnticlockwise = true;
							}
							double val = edgeLoop[i].Center.DistanceTo(edgeLoop[j].Center);
							double val2 = Math.Abs(edgeLoop[i].Radius - edgeLoop[j].Radius);
							if (Geometry.GreaterThan(val, Common.MMToFeet(1.0)) || Geometry.GreaterThan(val2, Common.MMToFeet(1.0)))
							{
								goto IL_280;
							}
							double bulge = Geometry.GetBulge(xyz, xyz2, edgeLoop[i].Center, isAnticlockwise);
							edgeInfo = new EdgeInfo(xyz, xyz2, bulge);
						}
						else
						{
							if (!Geometry.IsParallel(edgeLoop[i].Normal, edgeLoop[j].Normal, 1E-09))
							{
								goto IL_280;
							}
							edgeInfo = new EdgeInfo(xyz, xyz2, 0.0);
						}
						edgeLoop.RemoveAt(j);
						j--;
						if (edgeInfo != null)
						{
							edgeLoop[i] = edgeInfo;
						}
					}
					IL_280:;
				}
			}
		}

		public bool ExtractionBaseLineByView()
		{
			this.m_BaseLineSegmentLinkedGraph.Clear();
			this.m_CurrentBaseLineRevitCurves.Clear();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc).OfClass(typeof(CurveElement));
			foreach (Element baseLine in filteredElementCollector)
			{
				this.ExtractionOneBaseLineByCurveElement(baseLine);
			}
			return true;
		}

		public bool ExtractionBaseLineBySelection(List<Element> baseLineList)
		{
			foreach (Element baseLine in baseLineList)
			{
				this.ExtractionOneBaseLineByCurveElement(baseLine);
			}
			return true;
		}

		private bool ExtractionOneBaseLineByCurveElement(Element baseLine)
		{
			bool result;
			try
			{
				DetailCurve detailCurve = baseLine as DetailCurve;
				if (detailCurve == null)
				{
					result = false;
				}
				else if (detailCurve.LineStyle.Name.CompareTo("TempLine") == 0)
				{
					this.m_CurrentBaseLineRevitCurves.Add(baseLine.Id);
					result = false;
				}
				else if (detailCurve.LineStyle.Name.CompareTo("AprollBaseLine") != 0)
				{
					result = false;
				}
				else
				{
					this.m_CurrentBaseLineRevitCurves.Add(baseLine.Id);
					EdgeInfo edgeInfo = new EdgeInfo(detailCurve.GeometryCurve, true);
					BaseLineSegment segment = new BaseLineSegment(edgeInfo);
					string text = "";
					if (!this.AddBaseLineSegment(segment, ref text))
					{
						result = false;
					}
					else
					{
						result = true;
					}
				}
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public bool GetPathList(ref List<List<EdgeInfo>> aprollPathList)
		{
			List<List<BaseLineSegment>> list = new List<List<BaseLineSegment>>();
			if (!this.m_BaseLineSegmentLinkedGraph.BaseLineSegmentLinkedGroup(ref list))
			{
				return false;
			}
			foreach (List<BaseLineSegment> list2 in list)
			{
				List<EdgeInfo> list3 = new List<EdgeInfo>();
				foreach (BaseLineSegment baseLineSegment in list2)
				{
					list3.Add(baseLineSegment.Segment);
				}
				aprollPathList.Add(list3);
			}
			return true;
		}

		public bool FindBaseLineSegment(EdgeInfo edgeInfo, ref BaseLineSegment findedSegment)
		{
			return this.m_BaseLineSegmentLinkedGraph.FindBaseLineSegment(edgeInfo, ref findedSegment);
		}

		public void ChangeBaseLineSegmentOrientation(BaseLineSegment segment)
		{
			this.m_BaseLineSegmentLinkedGraph.ChangeBaseLineSegmentOrientation(segment);
		}

		public bool AddBaseLineSegment(BaseLineSegment segment, ref string message)
		{
			return this.m_BaseLineSegmentLinkedGraph.AddBaseLineSegment(segment, ref message);
		}

		public void RedrawBaseLine()
		{
			Transaction transaction = new Transaction(this.m_Doc);
			transaction.Start("redraw baseline curves");
			this.ClearBaseLine();
			this.Redraw();
			transaction.Commit();
		}

		public void DeleteBaseLineElements()
		{
			Transaction transaction = new Transaction(this.m_Doc);
			transaction.Start("delete baseline curves");
			this.ClearBaseLine();
			transaction.Commit();
		}

		private void ClearBaseLine()
		{
			foreach (ElementId elementId in this.m_CurrentBaseLineRevitCurves)
			{
				try
				{
					this.m_Doc.Delete(elementId);
				}
				catch (Exception)
				{
				}
			}
			this.m_CurrentBaseLineRevitCurves.Clear();
		}

		private void Redraw()
		{
			CurveArray curveArray = new CurveArray();
			CurveArray curveArray2 = new CurveArray();
			List<BaseLineSegment> baseLineSegments = this.m_BaseLineSegmentLinkedGraph.GetBaseLineSegments();
			if (baseLineSegments.Count == 0)
			{
				return;
			}
			foreach (BaseLineSegment baseLineSegment in baseLineSegments)
			{
				Curve curve = baseLineSegment.Segment.ConvertTo(this.m_Revit.Application.Application);
				curveArray.Append(curve);
				this.DrawArrow(baseLineSegment, ref curveArray2);
			}
			try
			{
				DetailCurveArray detailCurveArray = this.m_Doc.Create.NewDetailCurveArray(this.m_ActiveView, curveArray);
				foreach (object obj in detailCurveArray)
				{
					DetailCurve detailCurve = (DetailCurve)obj;
					detailCurve.LineStyle = this.m_BaseLineStyle;
					this.m_CurrentBaseLineRevitCurves.Add(detailCurve.Id);
				}
				DetailCurveArray detailCurveArray2 = this.m_Doc.Create.NewDetailCurveArray(this.m_ActiveView, curveArray2);
				foreach (object obj2 in detailCurveArray2)
				{
					DetailCurve detailCurve2 = (DetailCurve)obj2;
					detailCurve2.LineStyle = this.m_TempLineStyle;
					this.m_CurrentBaseLineRevitCurves.Add(detailCurve2.Id);
				}
			}
			catch (Exception ex)
			{
				string message = ex.Message;
			}
		}

		private void DrawArrow(BaseLineSegment segment, ref CurveArray arrowCurveAry)
		{
			EdgeInfo segment2 = segment.Segment;
			XYZ xyz;
			XYZ xyz2;
			if (segment.Segment.IsArc)
			{
				XYZ center = segment2.Center;
				XYZ normal = segment2.Normal;
				xyz = Geometry.CalculatMidPoint(segment2.StartPoint, segment2.EndPoint, center, normal);
				xyz2 = (xyz - center).Normalize();
				if (normal.IsAlmostEqualTo(-XYZ.BasisZ))
				{
					xyz2 = -xyz2;
				}
			}
			else
			{
				xyz = Geometry.CalculatMidPoint(segment2.StartPoint, segment2.EndPoint);
				xyz2 = Geometry.RotateTo(segment2.Normal, -Math.PI*.5, XYZ.BasisZ);
			}
			double num = Common.MMToFeet(300.0);
			XYZ startPoint = xyz;
			XYZ xyz3 = xyz + xyz2 * num;
			XYZ xyz4 = Geometry.RotateTo(xyz2, -2.3561944901923448, XYZ.BasisZ);
			XYZ endPoint = xyz3 + xyz4 * (num / 2.0);
			XYZ xyz5 = Geometry.RotateTo(xyz2, 2.3561944901923448, XYZ.BasisZ);
			XYZ endPoint2 = xyz3 + xyz5 * (num / 2.0);
			Line line = YJKLineEx.YJKGetBound(startPoint, xyz3);
			arrowCurveAry.Append(line);
			Line line2 = YJKLineEx.YJKGetBound(xyz3, endPoint);
			arrowCurveAry.Append(line2);
			Line line3 = YJKLineEx.YJKGetBound(xyz3, endPoint2);
			arrowCurveAry.Append(line3);
		}

		private bool GetLineStyle()
		{
			Category category = this.m_Doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
			if (category == null)
			{
				return false;
			}
			if (!category.SubCategories.Contains("AprollBaseLine") && !this.CreateLineStyle(ref category, "AprollBaseLine"))
			{
				return false;
			}
			if (!category.SubCategories.Contains("TempLine") && !this.CreateLineStyle(ref category, "TempLine"))
			{
				return false;
			}
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc).OfClass(typeof(GraphicsStyle));
			foreach (Element element in filteredElementCollector)
			{
				GraphicsStyle graphicsStyle = element as GraphicsStyle;
				if (graphicsStyle != null)
				{
					if (graphicsStyle.Name.CompareTo("AprollBaseLine") == 0)
					{
						this.m_BaseLineStyle = graphicsStyle;
					}
					if (graphicsStyle.Name.CompareTo("TempLine") == 0)
					{
						this.m_TempLineStyle = graphicsStyle;
					}
				}
			}
			return this.m_BaseLineStyle != null && this.m_TempLineStyle != null;
		}

		private bool CreateLineStyle(ref Category lineCategory, string typeName)
		{
			Transaction transaction = new Transaction(this.m_Doc);
			bool result;
			try
			{
				transaction.Start("new line style");
				Category category = this.m_Doc.Settings.Categories.NewSubcategory(lineCategory, typeName);
				if (typeName.CompareTo("AprollBaseLine") == 0)
				{
					category.LineColor = new Color(byte.MaxValue, 0, byte.MaxValue);
					category.SetLineWeight(6, (Autodesk.Revit.DB.GraphicsStyleType)1);
				}
				else
				{
					category.LineColor = new Color(0, 0, byte.MaxValue);
					category.SetLineWeight(5, (Autodesk.Revit.DB.GraphicsStyleType)1);
				}
				transaction.Commit();
				result = true;
			}
			catch (Exception)
			{
				if (transaction != null && transaction.HasStarted() && !transaction.HasEnded())
				{
					transaction.RollBack();
				}
				result = false;
			}
			return result;
		}

		public const string m_StrBaseLineTypeName = "AprollBaseLine";

		public const string m_StrTempLineTypeName = "TempLine";

		private ExternalCommandData m_Revit;

		private Document m_Doc;

		private View m_ActiveView;

		private GraphicsStyle m_BaseLineStyle;

		private GraphicsStyle m_TempLineStyle;

		private List<ElementId> m_CurrentBaseLineRevitCurves = new List<ElementId>();

		private BaseLineSegmentLinkedGraph m_BaseLineSegmentLinkedGraph = new BaseLineSegmentLinkedGraph();
	}
}
